<?xml version="1.0"?>
<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="html" />

    <xsl:template match="/">
        <xsl:variable name="tests.root" select="test-results" />
<xsl:text disable-output-escaping="yes">&lt;!DOCTYPE html>
</xsl:text>
<html>
    <head>
        <title><xsl:value-of select="$tests.root/@name" /></title>
        <style>
        .plus {
            display: inline-block;
            width: 16px;
            height: 16px;
            background-image: url();
        }
        .minus {
            display: inline-block;
            width: 16px;
            height: 16px;
            background-image: url();
        }
        .check {
            display: inline-block;
            width: 16px;
            height: 16px;
            background-image: url();
        }
        .error {
            display: inline-block;
            width: 16px;
            height: 16px;
            background-image: url();
        }
        .ignored {
            display: inline-block;
            width: 16px;
            height: 16px;
            background-image: url();
        }
        .warning {
            display: inline-block;
            width: 16px;
            height: 16px;
            background-image: url();
        }

        body {
            font: 11pt helvetica, arial, sans-serif;
            margin: 0;
        }

        h1 {
            margin: 0.5ex 0;
        }

        div#header {
            background-color: #eee;
            border-bottom: 1px solid #ccc;
            padding: 1ex;
            padding-bottom: 0;
            margin: 0;
        }

        #summary table th {
            text-align: center;
            color: #999;
            padding: 0.1ex 1ex;
        }

        #summary table td {
            text-align: center;
            padding: 0.1ex 1ex;
        }

        div#details {
            padding: 1em;
        }

        #details blockquote {
            margin-top: 0.25em;
        }

        .progress-bar {
            /* I'm not happy with the amount of cajoling needed here.
            The goal is simply to have the progress bar be vertically
            aligned to the middle of the line */

            font-size: 1pt;
            position: relative;
            display: inline-block;
            height: 5pt;
            width: 25pt;
            border-bottom: 6pt solid transparent;
            vertical-align: text-bottom;
        }

        .progress-bar-big {
            width: 100%;
            height: 14pt;
            border-bottom: 0;
        }

        .progress-bar .passed-progress {
            display: inline-block;
            height: 100%;
            background-color: #74b443;
        }

        .progress-bar .ignored-progress {
            display: inline-block;
            height: 100%;
            background-color: #fbd829;
        }

        .progress-bar .failed-progress {
            display: inline-block;
            height: 100%;
            background-color: #ec2d21;
        }

        .test-name {
            margin-left: 1em;
        }

        .failure-info {
            border: 1px solid #ccc;
            background-color: #ddd;
            padding-left: 2em;
            margin: 0.5em;
        }

        .failure-message {

        }

        .stacktrace {
            overflow: scroll;
        }

        </style>
    </head>
    <body>
        <!-- Debug display of the embedded icons
        <div class="plus" />
        <div class="minus" />
        <div class="warning" />
        <div class="error" />
        <div class="check" />
        -->
        <xsl:variable name="tests.total"
            select="$tests.root/@total" />
        <xsl:variable name="tests.errors"
            select="$tests.root/@errors" />
        <xsl:variable name="tests.failures"
            select="$tests.root/@failures" />
        <xsl:variable name="tests.ignored"
            select="$tests.root/@ignored" />
        <xsl:variable name="tests.skipped"
            select="$tests.root/@skipped" />
        <xsl:variable name="tests.inconclusive"
            select="$tests.root/@inconclusive" />
        <xsl:variable name="tests.passed"
            select="$tests.total - $tests.errors - $tests.failures" />

        <xsl:variable name="tests.grandtotal"
            select="$tests.total + $tests.ignored + $tests.skipped" />


        <div id="report">
            <script>
                function toggleDiv(imgId, divId)
                {
                    eDiv = document.getElementById(divId);
                    eImg = document.getElementById(imgId);

                    if (eDiv.style.display == "none")
                    {
                        eDiv.style.display = "block";
                        eImg.className = "minus";
                    }
                    else
                    {
                        eDiv.style.display = "none";
                        eImg.className = "plus";
                    }
                }
            </script>
            <div id="header">
                <h1><xsl:value-of select="$tests.root/@name" /></h1>
                <div id="summary">
                    <table>
                        <tbody>
                            <!--<tr>
                                <th>Assemblies tested:</th>
                                <td><xsl:value-of select="count($tests.root)"/></td>
                            </tr>-->
                            <tr>
                                <th>executed</th>
                                <th>pass</th>
                                <xsl:if test="$tests.failures > 0"><th>fail</th></xsl:if>
                                <xsl:if test="$tests.errors > 0"><th>error</th></xsl:if>
                                <xsl:if test="$tests.inconclusive > 0"><th>inconclusive</th></xsl:if>
                                <xsl:if test="$tests.ignored > 0"><th>ignored</th></xsl:if>
                                <xsl:if test="$tests.skipped > 0"><th>skipped</th></xsl:if>
                            </tr>
                            <tr>
                                <td><xsl:value-of select="$tests.total"/></td>
                                <td><xsl:value-of select="$tests.passed"/></td>
                                <xsl:if test="$tests.failures > 0">
                                    <td><xsl:value-of select="$tests.failures"/></td>
                                </xsl:if>
                                <xsl:if test="$tests.errors > 0">
                                    <td><xsl:value-of select="$tests.errors"/></td>
                                </xsl:if>
                                <xsl:if test="$tests.inconclusive > 0">
                                    <td><xsl:value-of select="$tests.inconclusive"/></td>
                                </xsl:if>
                                <xsl:if test="$tests.ignored > 0">
                                    <td><xsl:value-of select="$tests.ignored"/></td>
                                </xsl:if>
                                <xsl:if test="$tests.skipped > 0">
                                    <td><xsl:value-of select="$tests.skipped" /></td>
                                </xsl:if>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
            <div class="progress-bar progress-bar-big">
                <xsl:call-template name="progressSegment">
                    <xsl:with-param name="value" select="$tests.passed" />
                    <xsl:with-param name="total" select="$tests.grandtotal" />
                    <xsl:with-param name="class">passed-progress</xsl:with-param>
                </xsl:call-template>

                <xsl:call-template name="progressSegment">
                    <xsl:with-param name="value" select="$tests.ignored + $tests.skipped" />
                    <xsl:with-param name="total" select="$tests.grandtotal" />
                    <xsl:with-param name="class">ignored-progress</xsl:with-param>
                </xsl:call-template>

                <xsl:call-template name="progressSegment">
                    <xsl:with-param name="value" select="$tests.errors + $tests.failures" />
                    <xsl:with-param name="total" select="$tests.grandtotal" />
                    <xsl:with-param name="class">failed-progress</xsl:with-param>
                </xsl:call-template>
            </div>
            <div id="details">
                <xsl:apply-templates select="$tests.root" />
            </div>
        </div>
    </body>
</html>
    </xsl:template>

    <xsl:template match="test-results">
        <xsl:variable name="test.suite.id" select="generate-id()" />
        <xsl:variable name="test.suite.name" select="./@name"/>
        <xsl:variable name="failure.count" select="count(.//results//test-case[@success='False'])" />
        <xsl:variable name="ignored.count" select="count(.//results//test-case[@executed='False'])" />

        <!-- Suite status icon -->
        <xsl:choose>
            <xsl:when test="$failure.count > 0">
                <div class="error">
                    <xsl:attribute name="title">Failed tests: <xsl:value-of select="$failure.count" /></xsl:attribute>
                </div>
            </xsl:when>
            <xsl:when test="$ignored.count > 0">
                <div class="ignored">
                    <xsl:attribute name="title">Ignored tests: <xsl:value-of select="$ignored.count" /></xsl:attribute>
                </div>
            </xsl:when>
            <xsl:otherwise>
                <div class="check" />
            </xsl:otherwise>
        </xsl:choose>

        <!-- Suite expand/collapse -->
        <div class="minus">
            <xsl:attribute name="id">img<xsl:value-of select="$test.suite.id"/></xsl:attribute>
            <xsl:attribute name="onclick">javascript:toggleDiv('img<xsl:value-of select="$test.suite.id"/>', 'divDetails<xsl:value-of select="$test.suite.id"/>');</xsl:attribute>
        </div>

        <span class="suite-name">
            <xsl:value-of select="$test.suite.name"/>
        </span>

        <!-- Suite details -->
        <div>
            <xsl:attribute name="id">divDetails<xsl:value-of select="$test.suite.id"/></xsl:attribute>
            <blockquote>
                <!-- The test classes, with failed tests grouped together at the top -->
                <xsl:apply-templates select=".//test-suite[@type='TestFixture'][results//test-case]">
                    <!-- Group by outcome, with failed tests first -->
                    <xsl:sort select="@success" order="ascending" data-type="text"/>
                    <!-- Then sort by name within the groups -->
                    <xsl:sort select="@name" order="ascending" data-type="text"/>
                </xsl:apply-templates>
            </blockquote>
        </div>
    </xsl:template>

    <xsl:template match="test-suite">
        <xsl:variable name="passedtests.list" select="results//test-case[@success='True']"/>
        <xsl:variable name="ignoredtests.list" select="results//test-case[@executed='False']"/>
        <xsl:variable name="failedtests.list" select="results//test-case[@success='False']"/>
        <xsl:variable name="tests.count" select="count(results//test-case)"/>
        <xsl:variable name="passedtests.count" select="count($passedtests.list)"/>
        <xsl:variable name="ignoredtests.count" select="count($ignoredtests.list)"/>
        <xsl:variable name="failedtests.count" select="count($failedtests.list)"/>

        <xsl:variable name="fixture.name">
            <xsl:call-template name="getFullFixtureName">
                <xsl:with-param name="node" select="."/>
            </xsl:call-template>
        </xsl:variable>
        <div>
            <div class="progress-bar">
                <xsl:call-template name="progressSegment">
                    <xsl:with-param name="value" select="$passedtests.count" />
                    <xsl:with-param name="total" select="$tests.count" />
                    <xsl:with-param name="class">passed-progress</xsl:with-param>
                </xsl:call-template>

                <xsl:call-template name="progressSegment">
                    <xsl:with-param name="value" select="$ignoredtests.count" />
                    <xsl:with-param name="total" select="$tests.count" />
                    <xsl:with-param name="class">ignored-progress</xsl:with-param>
                </xsl:call-template>

                <xsl:call-template name="progressSegment">
                    <xsl:with-param name="value" select="$failedtests.count" />
                    <xsl:with-param name="total" select="$tests.count" />
                    <xsl:with-param name="class">failed-progress</xsl:with-param>
                </xsl:call-template>
            </div>
            <div class="plus">
                <xsl:attribute name="id">imgTestCase_<xsl:value-of select="@name"/></xsl:attribute>
                <xsl:attribute name="onClick">
                    <xsl:text>javascript:toggleDiv('imgTestCase_</xsl:text>
                    <xsl:value-of select="$fixture.name"/>
                    <xsl:text>', 'divTest_</xsl:text>
                    <xsl:value-of select="$fixture.name"/>
                    <xsl:text>');</xsl:text>
                </xsl:attribute>
            </div>
            <a>
                <xsl:attribute name="name"><xsl:value-of select="$fixture.name"/></xsl:attribute>
                <xsl:value-of select="$fixture.name"/>
            </a>
            (<xsl:value-of select="$passedtests.count"/>/<xsl:value-of select="$tests.count"/>)

            <div style="display:none">
                <xsl:attribute name="id">divTest_<xsl:value-of select="$fixture.name"/></xsl:attribute>

                <xsl:apply-templates select="$failedtests.list"/>
                <xsl:apply-templates select="$ignoredtests.list"/>
                <xsl:apply-templates select="$passedtests.list"/>
            </div>
        </div>
    </xsl:template>

    <xsl:template match="test-case">
        <div>
            <xsl:if test="position() mod 2 = 0">
                <xsl:attribute name="class">section-oddrow</xsl:attribute>
            </xsl:if>

            <xsl:choose>
                <xsl:when test="./@executed='False'">
                    <div class="ignored" />
                </xsl:when>
                <xsl:when test="./@success='False'">
                    <div class="error" />
                </xsl:when>
                <xsl:otherwise>
                    <div class="check" />
                </xsl:otherwise>
            </xsl:choose>

            <span class="test-name">
                <xsl:call-template name="getTestName">
                    <xsl:with-param name="node" select="."/>
                </xsl:call-template>
            </span>

            <xsl:choose>
                <xsl:when test="./@executed='False'">
                    <xsl:value-of select="substring-after(reason/message, '-')"/>
                </xsl:when>
                <xsl:when test="./@success='False'">
                    <div class="failure-info">
                        <div class="failure-message">
                            <xsl:value-of select="failure/message"/>
                        </div>
                        <pre class="stacktrace">
                            <xsl:value-of select="failure/stack-trace"/>
                        </pre>
                    </div>
                </xsl:when>
            </xsl:choose>
        </div>
    </xsl:template>
    <xsl:template name="getFullFixtureName">
        <xsl:param name="node" />

        <xsl:for-each select="ancestor::test-suite[@type='TestFixture']/@name">
            <xsl:value-of select="." />
            <xsl:text>.</xsl:text>
        </xsl:for-each>
        <xsl:value-of select="@name" />
    </xsl:template>

    <xsl:template name="getTestName">
        <xsl:param name="node" />

        <!-- Concatenate ancestor namespaces into: One.Two.Three.  -->
        <xsl:variable name="namespace">
            <xsl:for-each select="ancestor::test-suite[@type='Namespace']/@name">
                <xsl:value-of select="." />
                <xsl:text>.</xsl:text>
            </xsl:for-each>
        </xsl:variable>
        <xsl:variable name="fixture.name">
            <xsl:value-of select="ancestor::test-suite[@type='TestFixture']/@name" />
        </xsl:variable>

        <!-- Remove the namespace and fixture name from the test name -->
        <xsl:value-of select="substring(@name, string-length($namespace) + 1 + string-length($fixture.name) + 1)" />
    </xsl:template>

    <xsl:template name="progressSegment">
        <xsl:param name="value" />
        <xsl:param name="total" />
        <xsl:param name="class" />

        <xsl:variable name="percent" select="($value * 100) div $total" />

        <xsl:if test="$value > 0">
            <div class="{$class}">
                <xsl:attribute name="style">width: <xsl:value-of select="floor($percent * 100) div 100"/>%</xsl:attribute>
                &#160;
            </div>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
